﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;

namespace belov_test
{
    public partial class AuthorizationForm : Form
    {
        public const string USERS_DATA_DIRECTORY_PATH = "usersData";

        private const string USER_FIRST_LABEL = "Фамилия";
        private const string USER_SECOND_LABEL = "Имя";
        private const string ADMIN_FIRST_LABEL = "Логин";
        private const string ADMIN_SECOND_LABEL = "Пароль";
        private const string BANNED_SYMBOLS = " !@#$%^&*()0123456789?/,.";

        public const string USERS_DATA_FILE_PATH = "usersData\\users.xml";
        public const string ADMINS_DATA_FILE_PATH = "usersData\\admins.xml";

        public delegate void UserAuthEventHandler(UserInfo userInfo);
        public event UserAuthEventHandler UserAuth;

        public delegate void AdminAuthEventHandler(String login);
        public event AdminAuthEventHandler AdminAuth;

        public AuthorizationForm()
        {
            InitializeComponent();
        }

        private void OnAdminCbClick(object sender, EventArgs e)
        {
            if (!m_adminCB.Checked)
            {
                SwitchToUserView();
            }
            else
            {
                SwitchToAdminView();
            }

            CheckInputData();
        }

        private void SwitchToUserView()
        {
            m_firstLabel.Text = USER_FIRST_LABEL;
            m_secondLabel.Text = USER_SECOND_LABEL;

            m_secondTB.UseSystemPasswordChar = false;
            m_secondTB.Text = "";

            m_thirdLabel.Visible = m_thirdTB.Visible = true;
        }

        private void SwitchToAdminView()
        {
            m_firstLabel.Text = ADMIN_FIRST_LABEL;
            m_secondLabel.Text = ADMIN_SECOND_LABEL;

            m_secondTB.UseSystemPasswordChar = true;
            m_secondTB.Text = "";

            m_thirdLabel.Visible = m_thirdTB.Visible = false;
        }

        private void OnExitBtnClick(object sender, EventArgs e)
        {
            Environment.Exit(0);
        }

        private void OnFirstTBTextChanged(object sender, EventArgs e)
        {
            CheckForBannedSymbols(m_firstTB);
            CheckInputData();
        }

        private void OnThirdTBTextChanged(object sender, EventArgs e)
        {
            if (!m_adminCB.Checked)
            {
                CheckForBannedSymbols(m_thirdTB);
            }

            CheckInputData();
        }

        private void CheckForBannedSymbols(TextBox tb)
        {
            if (tb.Text.Length > 0)
            {
                if (BANNED_SYMBOLS.Contains(tb.Text[tb.Text.Length - 1].ToString()))
                {
                    tb.Text = m_firstTB.Text.Substring(0, tb.Text.Length - 1);
                }
            }
        }

        private void CheckInputData()
        {
            if (m_firstTB.Text.Length > 0 && m_secondTB.Text.Length > 0 && 
                (m_thirdTB.Text.Length > 0 || m_thirdTB.Visible == false))
            {
                m_okBtn.Enabled = true;
            }
            else
            {
                m_okBtn.Enabled = false;
            }
        }

        private void OnOkBtnClick(object sender, EventArgs e)
        {
            Authorization();
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter && m_okBtn.Enabled)
            {
                Authorization();
            }

            /*if (e.KeyCode == Keys.F1)
            {
                MessageBox.Show("Выполнили студенты группы ПС-42:\n    Иванов Е. Ю.\n    Шадрин С.А.\n\n(c) 2014г",
                                "Мир всем!", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }*/
        }

        private void Authorization()
        {
            if (m_adminCB.Checked)
            {
                if (AuthAdmin())
                {
                    if (AdminAuth != null)
                    {
                        AdminAuth(m_firstTB.Text.Trim());
                    }
                    Close();
                } 
                else
                {
                    MessageBox.Show("Неверное имя пользователи и пароль!", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                if (!Directory.Exists(USERS_DATA_DIRECTORY_PATH))
                {
                    Directory.CreateDirectory(USERS_DATA_DIRECTORY_PATH);
                }

                if (!File.Exists(USERS_DATA_FILE_PATH))
                {
                    CreateUsersFile();
                }

                Guid guid = GetCurrentUserGuid();

                if (guid == Guid.Empty)
                {
                    return;
                }

                UserAuthEventHandler handler = UserAuth;
                if (handler != null)
                {
                    UserInfo userInfo = new UserInfo(m_firstTB.Text, m_secondTB.Text, m_thirdTB.Text, guid);
                    handler(userInfo);
                }

                Close();
            }
        }

        private void CreateUsersFile()
        {
            XmlTextWriter xmlWriter = new XmlTextWriter(USERS_DATA_FILE_PATH, Encoding.UTF8);
            xmlWriter.Formatting = Formatting.Indented;
            xmlWriter.WriteStartDocument();
            xmlWriter.WriteStartElement("users");
            xmlWriter.WriteFullEndElement();
            xmlWriter.Close();
        }

        private Guid GetCurrentUserGuid()
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(USERS_DATA_FILE_PATH);
            XmlNodeList userNodes = xmlDocument.GetElementsByTagName("users")[0].ChildNodes;

            Guid userGuid = Guid.NewGuid();

            for (int i = 0; i < userNodes.Count; i++)
            {
                XmlAttributeCollection userNodeAttributes = userNodes[i].Attributes;

                string currentName = "";
                string currentSurname = "";
                string currentPatronymic = "";
                string currentGuid = "";

                for (int j = 0; j < userNodeAttributes.Count; j++)
                {
                    switch (userNodeAttributes[j].Name)
                    {
                        case "name":
                        {
                            currentName = userNodeAttributes[j].Value;
                            break;
                        }
                        case "patronymic":
                        {
                            currentPatronymic = userNodeAttributes[j].Value;
                            break;
                        }
                        case "surname":
                        {
                            currentSurname = userNodeAttributes[j].Value;
                            break;
                        }
                        case "guid":
                        {
                            currentGuid = userNodeAttributes[j].Value;
                            break;
                        }
                    }
                }

                if (m_secondTB.Text == currentName && 
                    m_thirdTB.Text == currentPatronymic && 
                    m_firstTB.Text == currentSurname)
                {
                    userGuid = new Guid(currentGuid);
                    break;
                }

                if ((i + 1) == userNodes.Count)
                {
                    if (MessageBox.Show("Указанный пользователь не найден. Cоздать?", "Не найден пользователь", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        WriteCurrentUserInfo(xmlDocument, userGuid);
                        return userGuid;
                    }
                    else
                    {
                        return Guid.Empty;
                    }
                }
            }

            if (userNodes.Count == 0)
            {
                if (MessageBox.Show("Указанный пользователь не найден. Cоздать?", "Не найден пользователь", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    WriteCurrentUserInfo(xmlDocument, userGuid);
                }
                else
                {
                    return Guid.Empty;
                }
            }

            return userGuid;
        }

        private void WriteCurrentUserInfo(XmlDocument xmlDocument, Guid guid)
        {
            XmlElement newUserInfo = xmlDocument.CreateElement("user");

            newUserInfo.SetAttribute("surname", m_firstTB.Text);
            newUserInfo.SetAttribute("name", m_secondTB.Text);
            newUserInfo.SetAttribute("patronymic", m_thirdTB.Text);
            newUserInfo.SetAttribute("guid", guid.ToString());

            xmlDocument.GetElementsByTagName("users")[0].AppendChild(newUserInfo);
            xmlDocument.Save(USERS_DATA_FILE_PATH);
        }

        private void CreateDefaultAdminsFile()
        {
            XmlTextWriter xmlWriter = new XmlTextWriter(ADMINS_DATA_FILE_PATH, Encoding.UTF8);
            xmlWriter.Formatting = Formatting.Indented;
            xmlWriter.WriteStartDocument();
            xmlWriter.WriteStartElement("admins");
            xmlWriter.WriteFullEndElement();
            xmlWriter.Close();

            XmlDocument adminsXml = new XmlDocument();
            adminsXml.Load(ADMINS_DATA_FILE_PATH);
            XmlElement admin = adminsXml.CreateElement("admin");
            admin.SetAttribute("login", "admin");
            admin.SetAttribute("password", "admin");
            adminsXml.GetElementsByTagName("admins")[0].AppendChild(admin);

            adminsXml.Save(ADMINS_DATA_FILE_PATH);
        }

        private bool AuthAdmin()
        {
            if (!Directory.Exists(USERS_DATA_DIRECTORY_PATH))
            {
                Directory.CreateDirectory(USERS_DATA_DIRECTORY_PATH);
            }

            if (!File.Exists(ADMINS_DATA_FILE_PATH))
            {
                CreateDefaultAdminsFile();
            }

            XmlDocument adminsXml = new XmlDocument();
            adminsXml.Load(ADMINS_DATA_FILE_PATH);
            XmlNodeList adminsNodes = adminsXml.GetElementsByTagName("admins")[0].ChildNodes;

            String enteredLogin = m_firstTB.Text.Trim();
            String enteredPassword = m_secondTB.Text.Trim();
            
            String login = "";
            String password = "";

            for (int i = 0; i < adminsNodes.Count; i++)
            {
                XmlAttributeCollection adminsNodeAttributes = adminsNodes[i].Attributes;

                for (int j = 0; j < adminsNodeAttributes.Count; j++)
                {
                    switch (adminsNodeAttributes[j].Name)
                    {
                        case "login":
                            {
                                login = adminsNodeAttributes[j].Value;
                                break;
                            }
                        case "password":
                            {
                                password = adminsNodeAttributes[j].Value;
                                break;
                            }
                    }
                }

                if ((enteredLogin == login) && (enteredPassword == password))
                {
                    return true;
                }
            }
            return false;
        }

        private void OnSecondTBTextChanged(object sender, EventArgs e)
        {
            if (!m_adminCB.Checked)
            {
                CheckForBannedSymbols(m_thirdTB);
            }

            CheckInputData();
        }
    }
}
